﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security;
using System.Security.Permissions;
using System.Text;

namespace Utilities
{
    /// <summary>
    /// utilities class with common methods
    /// </summary>
    public class Utils
    {
        public static FinancialStartEnd FinancialYear;
        public static DateTime April;
        public static DateTime May;
        public static DateTime June;
        public static DateTime July;
        public static DateTime August;
        public static DateTime September;
        public static DateTime October;
        public static DateTime November;
        public static DateTime December;
        public static DateTime January;
        public static DateTime February;
        public static DateTime March;
        public static DateTime AprilNext;
        
        static Utils()
        {
            FinancialYear = GetFinancialYearStartEnd(DateTime.Now);
            April = new DateTime(FinancialYear.FinancialYearStart, 4, 1);
            May = new DateTime(FinancialYear.FinancialYearStart, 5, 1);
            June = new DateTime(FinancialYear.FinancialYearStart, 6, 1);
            July = new DateTime(FinancialYear.FinancialYearStart, 7, 1);
            August = new DateTime(FinancialYear.FinancialYearStart, 8, 1);
            September = new DateTime(FinancialYear.FinancialYearStart, 9, 1);
            October = new DateTime(FinancialYear.FinancialYearStart, 10, 1);
            November = new DateTime(FinancialYear.FinancialYearStart, 11, 1);
            December = new DateTime(FinancialYear.FinancialYearStart, 12, 1);
            January = new DateTime(FinancialYear.FinancialYearEnd, 1, 1);
            February = new DateTime(FinancialYear.FinancialYearEnd, 2, 1);
            March = new DateTime(FinancialYear.FinancialYearEnd, 3, 1);
            AprilNext = new DateTime(FinancialYear.FinancialYearEnd, 4, 1);
        }
    

        public static void CopyFiles(string rootFolderPath,
                                       Dictionary<string, byte[]> filesToSave)
        {
            if (!Directory.Exists(rootFolderPath))
            {
                try
                {
                    Directory.CreateDirectory(rootFolderPath);
                }
                catch { throw new FileCopyException("Could not save the uploaded files becuase the root folder to hold the files could not be created. Please check if there is sufficient disk space and if the user has permission on the configured root folder path present in the configuration file."); }
            }

            int errorCount = 0;
            foreach (string fileName in filesToSave.Keys)
            {
                string fullFilePath = Path.Combine(rootFolderPath, fileName);
                byte[] content = filesToSave[fileName];
                if (content != null) 
                {
                    try
                    {
                        File.WriteAllBytes(fullFilePath, content);
                    }
                    catch
                    {
                        errorCount++;
                    }
                }
            }

            if (errorCount > 0)
            {
                throw new FileCopyException("There was an error saving one or more of the uploaded files. It could possible because the content was not captured properly or there is not enough disk space.");
            }
        }

        public static FinancialStartEnd GetFinancialYearStartEnd(DateTime transactionDate)
        {
            int year = transactionDate.Year;
            int month = transactionDate.Month;

            int currentYear = DateTime.Now.Year;
            int currentMonth = DateTime.Now.Month;

            if ((year < currentYear) || (year == currentYear && month <= 3))
            {
                FinancialStartEnd financialStartEnd = new FinancialStartEnd();
                financialStartEnd.FinancialYearEnd = currentYear;
                financialStartEnd.FinancialYearStart = currentYear - 1;
                return financialStartEnd;
            }
            else
            {
                FinancialStartEnd financialStartEnd = new FinancialStartEnd();
                financialStartEnd.FinancialYearStart = currentYear;
                financialStartEnd.FinancialYearEnd= currentYear + 1;
                return financialStartEnd;
            }
        }

        public static decimal CountDecimalPlaces(decimal dec)
        {
            if (dec == 0)
            {
                return 0;
            }

            int[] bits = Decimal.GetBits(dec);
            int exponent = bits[3] >> 16;
            int result = exponent;
            long lowDecimal = bits[0] | (bits[1] >> 8);
            while ((lowDecimal % 10) == 0)
            {
                result--;
                lowDecimal /= 10;
            }
            return result;
        }

        public static bool CreateDestinationPath(string destinationPath)
        {
            if (string.IsNullOrEmpty(destinationPath))
            {
                return false;
            }

            try
            {
                string[] splitString = destinationPath.Split(new char[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
                if (splitString.Count() > 1)
                {
                    string path = splitString[0] + "\\";
                    for (int i = 1; i < splitString.Count(); i++)
                    {
                        path = Path.Combine(path, splitString[i]);
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                    }
                }

                return true;
            }
            catch
            {
                return false;
            }
        }

        public static string GetMonth(int monthNumber)
        {
            string month = string.Empty;
            switch (monthNumber)
            {
                case 1:
                    month = "Jan";
                    break;
                case 2:
                    month = "Feb";
                    break;
                case 3:
                    month = "Mar";
                    break;
                case 4:
                    month = "Apr";
                    break;
                case 5:
                    month = "May";
                    break;
                case 6:
                    month = "Jun";
                    break;
                case 7:
                    month = "Jul";
                    break;
                case 8:
                    month = "Aug";
                    break;
                case 9:
                    month = "Sep";
                    break;
                case 10:
                    month = "Oct";
                    break;
                case 11:
                    month = "Nov";
                    break;
                case 12:
                    month = "Dec";
                    break;

                default:
                    break;

            }

            return month;
        }

        public static bool IsCommaSeparatedListIdentical(string leftList, string rightList)
        {
            string[] leftSplit = leftList.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            string[] rightSplit = rightList.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);

            if (leftSplit == null || rightSplit == null)
            {
                return false;
            }

            if (leftSplit.Length != rightSplit.Length)
            {
                return false;
            }

            List<int> leftIntegerList = new List<int>();
            foreach (string leftString in leftSplit)
            {
                string leftIntString = leftString.Replace("[", string.Empty).Replace("]", string.Empty);
                try
                {
                    leftIntegerList.Add(int.Parse(leftIntString));
                }
                catch { }
            }


            List<int> rightIntegerList = new List<int>();
            foreach (string rightString in rightSplit)
            {
                string rightIntString = rightString.Replace("[", string.Empty).Replace("]", string.Empty);
                try
                {
                    rightIntegerList.Add(int.Parse(rightIntString));
                }
                catch { }
            }

            if (leftIntegerList.Count != rightIntegerList.Count)
            {
                return false;
            }

            leftIntegerList.Sort();
            rightIntegerList.Sort();

            for (int i = 0; i < leftIntegerList.Count; i++)
            {
                if (leftIntegerList[i] != rightIntegerList[i])
                {
                    return false;
                }
            }

            return true;
        }

        public static bool HasWritePermissions(string folderPath)
        {
            if(!Directory.Exists(folderPath))
            {
                return false;
            }

            var permission = new FileIOPermission(FileIOPermissionAccess.Write, folderPath);
            var permissionSet = new PermissionSet(PermissionState.None);
            permissionSet.AddPermission(permission);
            if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    public struct FinancialStartEnd
    {
        public int FinancialYearStart;
        public int FinancialYearEnd;
        public string Key
        {
            get
            {
                return FinancialYearStart.ToString() + FinancialYearEnd.ToString();
            }
        }
    }
}
